package org.baicaixiaozhan.tenet.reflection;

import org.baicaixiaozhan.tenet.reflection.aop.Advice;

import java.lang.reflect.InvocationHandler;

/**
 * Java 反射有关的静态实用程序
 *
 * @author baicaixiaozhan
 * @since 1.0.0
 */
public final class Reflection {

    private Reflection() {
        throw new AssertionError();
    }

    /**
     * 实例化对象
     *
     * @param clazz 目标对象 Class
     * @return T
     */
    public static <T> T newInstance(Class<T> clazz) {
        T instance = null;
        try {
            instance = clazz.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return instance;
    }

    /**
     * 实例化对象
     *
     * @param clazz 目标对象 Class
     * @param args 构造器参数
     * @return T
     */
    public static <T> T newInstance(Class<T> clazz, Object[] args) {
        T instance = null;
        try {
            instance = clazz.getDeclaredConstructor().newInstance(args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return instance;
    }

    /**
     * 返回指定接口的代理实例，该代理实例将方法调用调度到指定的调用处理程序。
     *
     * @param target 目标对象数组
     * @param invocationHandler 指定的调用处理程序
     * @return T 类型的代理对象
     */
    public static <T> T newProxyInstance(T[] target, InvocationHandler invocationHandler) {
        return (T) ProxyFactory.newProxy(target, invocationHandler);
    }

    /**
     * 返回指定接口的代理实例，该代理实例将方法调用调度到指定的调用处理程序。
     *
     * @param target 目标对象
     * @param invocationHandler 指定的调用处理程序
     * @return T 类型的代理对象
     */
    public static <T> T newProxyInstance(T target, InvocationHandler invocationHandler) {
        return (T) ProxyFactory.newProxy(target, invocationHandler);
    }

    /**
     * 返回指定接口的代理实例，该代理实例将方法调用调度到具有 Aspect 抽象语义的处理程序。
     *
     * @param target 目标对象
     * @param advice 具有 Aspect 抽象语义的处理程序
     * @return T 类型的具有 Aspect 抽象语义的代理对象
     */
    public static <T> T newProxyInstanceWithAspect(T target, Advice advice) {
        return (T) ProxyFactory.newProxy(target, advice);
    }

    /**
     * 返回指定接口的代理实例，该代理实例将方法调用调度到具有 Aspect 抽象语义的处理程序。
     *
     * @param target 目标对象
     * @param advice 具有 Aspect 抽象语义的处理程序
     * @return T 类型的具有 Aspect 抽象语义的代理对象
     */
    public static <T> T newProxyInstanceWithAspect(T target, Class<? extends Advice> advice) {
        return (T) ProxyFactory.newProxy(target, Reflection.newInstance(advice));
    }

    public static <T> T newProxyInstanceWithAspect(T target, Advice advice, Boolean enableCglib) {
        return (T) ProxyFactory.newProxy(target, advice,enableCglib);
    }
}
